﻿using QMERP.Infrastructure.Extensions;
using QMERP.Infrastructure.Tools;
using System.Data;

namespace QMERP.Domain.Dtos
{
    public static class LensDetailResponseExtension
    {
        /// <summary>
        /// XYStream表转LensDetails
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        public static List<LensDetailResponse> ToLensDetails(this Stream stream)
        {
            var workbook = stream.ToXLWorkbook();
            List<LensDetailResponse> list = new();
            for (int num = 1; num <= workbook.Worksheets.Count; num++)
            {
                var sheet = workbook.Worksheet(num);
                ExcelHelper.IsXYTable(sheet);
                string degreesType = sheet.Name.Substring(sheet.Name.Length - 1) + "/-";
                var headerRow = sheet.Row(2);//第2行为标题行  
                int cellCount = sheet.LastCellUsed().Address.ColumnNumber;
                int rowCount = sheet.LastRowUsed().RowNumber();
                for (int i = 2; i < cellCount ; i++)
                {
                    for (int j = 3; j < rowCount; j++)
                    {
                        var row = sheet.Row(j);
                        string sph = row.Cell(1).GetString();
                        string cyl = headerRow.Cell(i).GetString();
                        string qty = row.Cell(i).GetString();
                        LensDetailResponse model = new()
                        {
                            DegreesType = degreesType,
                            SPH = sph.Substring(1).ToInt(),
                            CYL = cyl.Substring(1).ToInt(),
                            Qty = qty == "" ? 0 : qty.ToInt()
                        };
                        model.CYL = model.CYL > 0 ? -model.CYL : model.CYL;
                        list.Add(model);
                    }
                }
            }
            return list;
        }

        /// <summary>
        /// XYTable转LensDetails
        /// </summary>
        /// <param name="xyTable"></param>
        /// <returns></returns>
        public static List<LensDetailResponse> ToLensDetails(DataTable xyTable)
        {
            int column = xyTable.Columns.Count;
            List<LensDetailResponse> list = new();
            int rowCount = xyTable.Rows.Count - 1;
            for (int i = 0; i < rowCount; i++)
            {
                DataRow dr = xyTable.Rows[i];
                for (int c = 1; c < column - 1; c++)
                {
                    string cyl = xyTable.Columns[c].ColumnName;
                    string sph = dr[0].ToString()!;
                    string qty = dr[c].ToString()!;
                    string degreesType = "-/-";
                    if (sph.ToInt() > 0)
                        degreesType = "+/-";
                    LensDetailResponse detail = new()
                    {
                        SPH = sph.ToInt(),
                        CYL = Math.Abs(cyl.ToInt()),
                        DegreesType = degreesType,
                        Qty = qty.ToInt(),
                    };
                    list.Add(detail);
                }
            }
            return list;
        }

        /// <summary>
        /// LensDetails转XYTable
        /// </summary>
        /// <param name="lensDetails"></param>
        /// <returns></returns>
        public static DataTable ToXYTable(this List<LensDetailResponse> lensDetails)
        {
            List<string> degreesTypes = lensDetails.Select(x => x.DegreesType).Distinct().ToList();
            var cylTitles = lensDetails.Select(s => s.CYL).OrderBy(x => x).Distinct().ToList();
            DataTable dt = new();
            dt.Columns.Add("SPH");
            foreach (var cylTitle in cylTitles)
            {
                string cyl = cylTitle.ToString().PadLeft(3, '0');
                if (cyl != "000")
                    cyl = "-" + cyl;
                dt.Columns.Add(cyl);
            }
            dt.Columns.Add("Total");
            int column = dt.Columns.Count;
            foreach (var degreesType in degreesTypes)
            {
                var list = lensDetails.Where(x => x.DegreesType == degreesType).ToList();
                var sphTitles = list.Select(s => s.SPH).OrderBy(Math.Abs).Distinct().ToList();
                foreach (var sph in sphTitles)
                {
                    DataRow dr = dt.NewRow();
                    dr[0] = sph;
                    int qty = 0;
                    for (int c = 1; c < column - 1; c++)
                    {
                        int cyl = Math.Abs(dt.Columns[c].ColumnName.ToInt());
                        var detail = list.FirstOrDefault(x => x.SPH == sph && x.CYL == cyl);
                        if (detail == null)
                        {
                            break;
                        }
                        dr[c] = detail.Qty != 0 ? detail.Qty : "";
                        qty += detail.Qty;
                    }
                    dr[dt.Columns.Count - 1] = qty;
                    dt.Rows.Add(dr);
                }


            }
            DataRow drTotal = dt.NewRow();
            drTotal[0] = "Total";
            for (int c = 1; c < column - 1; c++)
            {
                int cyl = Math.Abs(dt.Columns[c].ColumnName.ToInt());
                var total = lensDetails.Where(x => x.CYL == cyl).Sum(x => x.Qty);
                drTotal[c] = total;
            }
            drTotal[dt.Columns.Count - 1] = lensDetails.Sum(x => x.Qty);
            dt.Rows.Add(drTotal);
            return dt;
        }

        /// <summary>
        /// 对比光度是否都一致
        /// </summary>
        /// <param name="lensDetails"></param>
        /// <param name="lensDetailsOther"></param>
        /// <returns></returns>
        //public static bool IsSame(this List<LensDetailResponse> lensDetails, List<LensDetailResponse> lensDetailsOther)
        //{
        //    return !lensDetails.Where(a => !lensDetailsOther.Exists(b => a.SPH == b.SPH && a.CYL == b.CYL)).Any();
        //}

        /// <summary>
        /// 度数是否在镜种范围内
        /// </summary>
        /// <param name="lensDetails"></param>
        /// <param name="lens"></param>
        /// <returns></returns>
        public static bool InRange(this List<LensDetailResponse> lensDetails, LensResponse lens)
        {
            if (lensDetails.Count <= 0)
                return true;
            int minSPH = lensDetails.Min(x => x.SPH);
            int maxSPH = lensDetails.Max(x => x.SPH);
            int minCYL = lensDetails.Min(x => x.CYL);
            int maxCYL = lensDetails.Max(x => x.CYL);
            if (minSPH >= lens.MinSPH && maxSPH <= lens.MaxSPH && minCYL >= lens.MinSPH && maxCYL <= lens.MaxCYL)
            {
                return true;
            }
            return false;
        }
        /// <summary>
        /// 度数是否在镜种范围内
        /// </summary>
        /// <param name="lensDetails"></param>
        /// <param name="lens"></param>
        /// <returns></returns>
        public static bool InRange(this List<LensDetailResponse> lensDetails, Contract_LensResponse lens)
        {
            if (lensDetails.Count <= 0)
                return true;
            int minSPH = lensDetails.Min(x => x.SPH);
            int maxSPH = lensDetails.Max(x => x.SPH);
            int minCYL = lensDetails.Min(x => x.CYL);
            int maxCYL = lensDetails.Max(x => x.CYL);
            if (minSPH >= lens.MinSPH && maxSPH <= lens.MaxSPH && minCYL >= lens.MinSPH && maxCYL <= lens.MaxCYL)
            {
                return true;
            }
            return false;
        }
    }
}
